﻿using System;
using System.Collections.Generic;

using System.Text;
using Efficient.Domain;
using System.Reflection;

namespace Efficient.DataAccess
{
    public class EntityQueryBuilder : IEntityQueryBuilder
    {
        private static readonly Dictionary<Type, KeywordTable> keywordTableCache = new Dictionary<Type, KeywordTable>();
        private readonly IDbService dao;

        public EntityQueryBuilder(IDbService dao)
        {
            this.dao = dao;
        }

        #region IEntityQueryBuilder Members

        public KeywordQuery BuildKeywordPart<T>()
        {
            return BuildKeywordPart<T>(string.Empty);
        }

        public KeywordQuery BuildKeywordPart<T>(string prix)
        {
            Type clazz = typeof(T);
            return BuildKeywordPart(clazz, prix);
        }

        public KeywordQuery BuildKeywordPart(Type clazz)
        {
            return BuildKeywordPart(clazz, string.Empty);
        }

        public KeywordQuery BuildKeywordPart(Type clazz, string prix)
        {
            KeywordTable table = GetTable(clazz);
            return table.BuildKeywordQueryPart(prix);
        }

        private KeywordTable GetTable(Type clazz)
        {
            KeywordTable table = BuildKeywordTable(clazz);
            if (table == null)
            {
                throw new NotSupportedException("类型：" + clazz.FullName + " 不支持创建关键字查询");
            }
            table.Dao = this.dao;
            return table;
        }

        public KeywordQuery BuildQueryByKeyword<T>(params OrderField[] orderBy)
        {
            return BuildQueryByKeyword<T>(string.Empty, orderBy);
        }

        public KeywordQuery BuildQueryByKeyword<T>(string prix, params OrderField[] orderBy)
        {
            Type clazz = typeof(T);
            return BuildQueryByKeyword(clazz, prix, orderBy);
        }

        public KeywordQuery BuildQueryByKeyword(Type clazz, params OrderField[] orderBy)
        {
            return BuildQueryByKeyword(clazz,string.Empty, orderBy);
        }

        public KeywordQuery BuildQueryByKeyword(Type clazz, string prix, params OrderField[] orderBy)
        {
            KeywordTable table = GetTable(clazz);
            return table.BuildQueryByKeyword(prix, orderBy);
        }

        public string BuildQueryAll(Type clazz, params OrderField[] orderBy)
        {
            return BuildQueryAll(clazz, string.Empty, orderBy);
        }

        public string BuildQueryAll(Type clazz, string prix, params OrderField[] orderBy)
        {
            KeywordTable table = GetTable(clazz);
            return table.BuildQueryAll(prix, orderBy);
        }

        public string BuildQueryAll<T>(params OrderField[] orderBy)
        {
            return BuildQueryAll<T>(string.Empty, orderBy);
        }

        public string BuildQueryAll<T>(string prix, params OrderField[] orderBy)
        {
            Type clazz = typeof(T);
            return BuildQueryAll(clazz, prix, orderBy);
        }
        #endregion

        private static KeywordTable BuildKeywordTable(Type clazz)
        {
            if (!keywordTableCache.ContainsKey(clazz))
            {
                object[] attr = clazz.GetCustomAttributes(false);
                KeywordTable table = null;
                foreach (Attribute attrItem in attr)
                {
                    if (attrItem is MappingTableAttribute)
                    {
                        MappingTableAttribute tableMapping = (MappingTableAttribute)attrItem;
                        table = new KeywordTable(tableMapping.TableName);
                        break;
                    }
                }
                if (table != null)
                {
                    PropertyInfo[] fields = clazz.GetProperties();
                    foreach (PropertyInfo pItem in fields)
                    {
                        object[] pAttr = pItem.GetCustomAttributes(false);
                        foreach (Attribute attrItem in pAttr)
                        {
                            if (attrItem is KeywordAttribute)
                            {
                                KeywordAttribute item = ((KeywordAttribute)attrItem);
                                table.AddField(item.Field, item.Mode);
                                break;
                            }
                        }
                    }
                }
                keywordTableCache[clazz] = table;
            }
            return keywordTableCache[clazz];
        }
    }

}
